package com.radar.io;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.amazonaws.util.IOUtils;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.radar.common.RadarSite;
import org.meteoinfo.data.mapdata.ShapeFileManage;
import org.meteoinfo.layer.VectorLayer;

import java.io.*;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class ShapeSourcePool {
    private static Log log = LogFactory.get();

    private static LoadingCache<String, Optional<VectorLayer>> dataSourceCache;

    static {
        LoadingCache<String, Optional<VectorLayer>> cache = null;
        dataSourceCache = CacheBuilder.newBuilder()
                .maximumSize(20)   //最大能缓存的容量
                .expireAfterAccess(2, TimeUnit.DAYS)  //过期策略：1天没被访问后过期
                .expireAfterWrite(2, TimeUnit.DAYS)  //过期策略：1天没被写入后过期
                .recordStats()  //开启统计功能
                .build(new CacheLoader<String, Optional<VectorLayer>>() {
                    @Override
                    public Optional<VectorLayer> load(String key) throws Exception {
                        return Optional.empty();
                    }
                });
    }
    public static VectorLayer getShapeCache(String key) throws Exception {
        if (key == null) {
            return null;
        }
        Optional<VectorLayer> dataSource;
        synchronized(dataSourceCache) {
            dataSource = dataSourceCache.get(key);
        }
        if(dataSource.isPresent()){
            return dataSource.get();
        }else{
            dataSource = getTmpLayer(key);
            if(dataSource == null || !dataSource.isPresent()){
                throw new IOException();
            }
            // put dataSource
            synchronized (dataSourceCache) {
                dataSourceCache.put(key, dataSource);
            }
        }
        return dataSource.get();
    }

    public static Optional<VectorLayer> getTmpLayer(String key) throws Exception {
        String tmpDirPath = FileUtil.getTmpDirPath();
        tmpDirPath = tmpDirPath + File.separator + "radar_shape_cache" + File.separator;
        FileUtil.del(tmpDirPath);
        String shapeDir = tmpDirPath + key + File.separator;
        String shpFile = shapeDir + key +".shp";
        if(FileUtil.exist(tmpDirPath + key + ".zip") && FileUtil.exist(shpFile)){
            return Optional.of(ShapeFileManage.loadShapeFile(shpFile,"gb2312"));
        }else{
            FileUtil.mkdir(shapeDir);
            try (InputStream stream = new RadarSite().getClass().getClassLoader().getResourceAsStream("shp"+ File.separator + key + ".zip")) {
                if (stream != null) {
                    FileUtil.writeBytes(IOUtils.toByteArray(stream), tmpDirPath + key + ".zip");
                }
                ZipUtil.unzip(tmpDirPath + key + ".zip");
                if(FileUtil.exist(shpFile)){
                    return Optional.of(ShapeFileManage.loadShapeFile(shpFile,"gb2312"));
                }
            } catch (IOException e) {
                log.error(ExceptionUtil.stacktraceToString(e));
            }
        }
        // key
        return null;
    }
}
